package com.pingan.framework.cat.config.internals;

import org.unidal.cat.config.ClientConfiguration;
import org.unidal.cat.config.ClientConfigurationListener;
import org.unidal.cat.config.ClientConfigurationManager;
import org.unidal.cat.config.ClientEnvironmentSettings;
import org.unidal.cat.config.internals.ClientConfigurationProvider;
import org.unidal.cat.config.internals.DefaultClientConfiguration;
import org.unidal.cat.config.internals.ServerDiscovery;
import org.unidal.helper.Splitters;
import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.annotation.Named;
import org.unidal.lookup.logging.LogEnabled;
import org.unidal.lookup.logging.Logger;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

@Named(type = ClientConfigurationManager.class)
public class DefaultClientConfigurationManager implements ClientConfigurationManager, LogEnabled {
   @Inject
   private ClientEnvironmentSettings m_settings;

   @Inject(type = ClientConfigurationProvider.class, value = "local")
   private ClientConfigurationProvider m_local;

   //@Inject(type = ClientConfigurationProvider.class, value = "remote")
   //private ClientConfigurationProvider m_remote;
   @Inject
   private ServerDiscovery m_discovery;

   private ClientConfiguration m_config;

   private List<ClientConfigurationListener> m_listeners = new ArrayList<ClientConfigurationListener>();

   private Logger m_logger;

   @Override
   public void enableLogging(Logger logger) {
      m_logger = logger;
   }

   private ClientConfiguration getRemoteConfig(){

      List<InetSocketAddress> servers = m_discovery.getMetaServers();

      for (InetSocketAddress server : servers) {
         InetAddress address = server.getAddress();

         if (address == null) {
            continue;
         }
         DefaultClientConfiguration configure = new DefaultClientConfiguration();

         String brokers = getAddress(address.getHostAddress()+":"+server.getPort());

         List<String> list = Splitters.by(',').noEmptyItem().trim().split(brokers.replace(';',','));
         for (String s:list) {
            String[] raw = s.split(":");
            configure.addServerForTree(raw[0], Integer.parseInt(raw[1]));
         }
         configure.setDomain(m_settings.getDomain());
         return configure;
      }

      return null;
   }

   private String getAddress(String metaServer){

      String url = String.format("http://%s/cat/s/router?domain=cat",metaServer);

      try {
         HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
         String str = bufferedReader.readLine();

         if(str!=null){
            int len = str.length();
            if(str.charAt(len-1)==';') {
               str = str.substring(0, len - 1);
            }
            m_logger.info("get cat servers from cat server - "+url);
         }

         return str;
      }catch (Throwable e){
         e.printStackTrace();
      }

      return "";
   }

   @Override
   public ClientConfiguration getConfig() {
      if(m_config == null) {
         ClientConfiguration config = getRemoteConfig();//m_remote.getConfiguration();

         if (config == null) {
            config = m_local.getConfiguration();
         }

         if (config == null) {
            config = new DefaultClientConfiguration();
            m_logger.warn("Unable to load client configuration, CAT is DISABLED!");
         }
         m_config = config;
      }

      return m_config;
   }

   @Override
   public void register(ClientConfigurationListener listener) {
      m_listeners.add(listener);
   }
}
